﻿// Vex Flow Notation
// Mohit Muthanna <mohit@muthanna.com>
//
// Copyright Mohit Muthanna 2010
//
// Requires vex.js.

/** @constructor */
Vex.Flow.TabRestNote = function (tab_struct) {
    if (arguments.length > 0) this.init(tab_struct);
}
Vex.Flow.TabRestNote.prototype = new Vex.Flow.Note();
Vex.Flow.TabRestNote.superclass = Vex.Flow.Note.prototype;
Vex.Flow.TabRestNote.constructor = Vex.Flow.TabRestNote;

Vex.Flow.TabRestNote.prototype.init = function (tab_struct) {
    var superclass = Vex.Flow.TabRestNote.superclass;
    superclass.init.call(this, tab_struct);

    // Note properties
    this.positions = tab_struct.positions; // [{ str: X, fret: X }]
    this.modifiers = [];
    this.render_options = {
        glyph_font_scale: 30 // font size for note heads and rests
    }

    this.noteGlyph =
      Vex.Flow.durationToGlyph(this.duration, this.noteType);
    if (!this.noteGlyph) {
        throw new Vex.RuntimeError("BadArguments",
            "Invalid note initialization data (No glyph found): " +
            JSON.stringify(tab_struct));
    }

    this.glyphs = [];
    this.width = 0;
    for (var i = 0; i < this.positions.length; ++i) {
        var fret = this.positions[i].fret;
        var glyph = Vex.Flow.tabToGlyph(fret);
        this.glyphs.push(glyph);
        this.width = (glyph.width > this.width) ? glyph.width : this.width;
    }
}

Vex.Flow.TabRestNote.prototype.setStave = function (stave) {
    var superclass = Vex.Flow.TabRestNote.superclass;
    superclass.setStave.call(this, stave);
    this.context = stave.context;
    this.width = 0;

    // Calculate the fret number width based on font used
    if (this.context) {
        for (var i = 0; i < this.glyphs.length; ++i) {
            var text = "" + this.glyphs[i].text;
            if (text.toUpperCase() != "X")
                this.glyphs[i].width = this.context.measureText(text).width;
            this.width = (this.glyphs[i].width > this.width) ?
              this.glyphs[i].width : this.width;
        }
    }

    var ys = [];

    // Setup y coordinates for score.
    for (var i = 0; i < this.positions.length; ++i) {
        var line = this.positions[i].str;
        ys.push(this.stave.getYForLine(line - 1));
    }

    return this.setYs(ys);
}

// Get the Tab Positions for each note in chord
Vex.Flow.TabRestNote.prototype.getPositions = function () {
    return this.positions;
}

Vex.Flow.TabRestNote.prototype.addToModifierContext = function (mc) {
    this.setModifierContext(mc);
    for (var i = 0; i < this.modifiers.length; ++i) {
        this.modifierContext.addModifier(this.modifiers[i]);
    }
    this.preFormatted = false;
    return this;
}

Vex.Flow.TabRestNote.prototype.addModifier = function (modifier, index) {
    modifier.setNote(this);
    modifier.setIndex(index || 0);
    this.modifiers.push(modifier);
    this.setPreFormatted(false);
    return this;
}

Vex.Flow.TabRestNote.prototype.getTieRightX = function () {
    var tieStartX = this.getAbsoluteX();
    var note_glyph_width = this.noteGlyph.head_width;
    tieStartX += (note_glyph_width / 2);
    tieStartX += ((-this.width / 2) + this.width + 2);

    return tieStartX;
}

Vex.Flow.TabRestNote.prototype.getTieLeftX = function () {
    var tieEndX = this.getAbsoluteX();
    var note_glyph_width = this.noteGlyph.head_width;
    tieEndX += (note_glyph_width / 2);
    tieEndX -= ((this.width / 2) + 2);

    return tieEndX;
}

Vex.Flow.TabRestNote.prototype.getModifierStartXY = function (position, index) {
    if (!this.preFormatted) throw new Vex.RERR("UnformattedNote",
        "Can't call GetModifierStartXY on an unformatted note");

    if (this.ys.length == 0) throw new Vex.RERR("NoYValues",
        "No Y-Values calculated for this note.");

    var x = 0;
    if (position == Vex.Flow.Modifier.Position.LEFT) {
        x = -1 * 2;  // extra_left_px
    } else if (position == Vex.Flow.Modifier.Position.RIGHT) {
        x = this.width + 2; // extra_right_px
    } else if (position == Vex.Flow.Modifier.Position.BELOW ||
               position == Vex.Flow.Modifier.Position.ABOVE) {
        var note_glyph_width = this.noteGlyph.head_width;
        x = note_glyph_width / 2;
    }

    return { x: this.getAbsoluteX() + x, y: this.ys[index] };
}

// Pre-render formatting
Vex.Flow.TabRestNote.prototype.preFormat = function () {
    if (this.preFormatted) return;
    if (this.modifierContext) this.modifierContext.preFormat();
    // width is already set during init()
    this.setPreFormatted(true);
}

Vex.Flow.TabRestNote.prototype.draw = function () {
    if (!this.context) throw new Vex.RERR("NoCanvasContext",
        "Can't draw without a canvas context.");
    if (!this.stave) throw new Vex.RERR("NoStave", "Can't draw without a stave.");
    if (this.ys.length == 0) throw new Vex.RERR("NoYValues",
        "Can't draw note without Y values.");

    var ctx = this.context;
    var x = this.getAbsoluteX();
    var ys = this.ys;

    for (var i = 0; i < this.positions.length; ++i) {
        var y = ys[i];

        var glyph = this.glyphs[i];

        // Center the fret text beneath the notation note head
        var note_glyph_width = this.noteGlyph.head_width;
        var tab_x = x + (note_glyph_width / 2) - (glyph.width / 2);

        ctx.clearRect(tab_x - 2, y - 3, glyph.width + 4, 6);

        if (glyph.code) {
           // Vex.Flow.renderGlyph(ctx, tab_x, y + 5 + glyph.shift_y,
           //     this.render_options.glyph_font_scale, glyph.code);
        } else {
            var text = glyph.text.toString();
            //ctx.fillText(text, tab_x, y + 5);
        }
    }

    // Draw the modifiers
    for (var i = 0; i < this.modifiers.length; ++i) {
        var modifier = this.modifiers[i];
        modifier.setContext(this.context);
        modifier.draw();
    }
}
